# 与用户相关的ORM模型
from exts import db
from datetime import datetime
from enum import Enum
from shortuuid import uuid
from werkzeug.security import generate_password_hash, check_password_hash


class PermissionEnum(Enum):
    BOARD = "板块"
    POST = "帖子"
    COMMENT = "评论"
    FRONT_USER = "前台用户"
    CMS_USER = "后台用户"

# 权限模型
class PermissionModel(db.Model):
    __tablename__ = "permission"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment="主键id")
    name = db.Column(db.Enum(PermissionEnum), nullable=False, unique=True, comment="权限名称")


role_permission_table = db.Table(
    "role_permission_table",
    db.Column("role_id", db.Integer, db.ForeignKey("role.id")),
    db.Column("permission_id", db.Integer, db.ForeignKey("permission.id"))
)

# 角色模型
class RoleModel(db.Model):
    __tablename__ = "role"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment="主键id")
    name = db.Column(db.String(100), nullable=False)
    desc = db.Column(db.String(100), nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.now)
    # 这行代码定义了
    # RoleModel
    # 和
    # PermissionModel
    # 之间的多对多关系。通过这个关系，我们可以方便地在
    # RoleModel
    # 实例中访问与之关联的
    # PermissionModel
    # 实例，反之亦然  secondary=role_permission_table: 这个参数指定了用于建立多对多关系的中间表
    permissions = db.relationship("PermissionModel", secondary=role_permission_table, backref="roles")

# 用户模型
class UserModel(db.Model):
    __tablename__ = "user"
    id = db.Column(db.String(100), primary_key=True, default=uuid)
    username = db.Column(db.String(100), nullable=False, unique=True)
    # password = db.Column(db.String(200), nullable=False)
    # _password代表是私有变量
    _password = db.Column(db.String(200), nullable=False)
    email = db.Column(db.String(100), nullable=False, unique=True, comment="邮箱")
    avatar = db.Column(db.String(100), comment="头像")
    signature = db.Column(db.String(100), comment="签名")
    join_time = db.Column(db.DateTime, default=datetime.now, comment="加入时间")
    is_staff = db.Column(db.Boolean, default=False, comment="是否是员工，只有员工才能进入后台")
    is_active = db.Column(db.Boolean, default=True, comment="是否可用")

    # 外键
    role_id = db.Column(db.Integer, db.ForeignKey("role.id"))
    role = db.relationship("RoleModel", backref="users")

    # 在__init__方法中，首先检查传入的kwargs中是否包含password键。如果包含，则调用
    # self.password的setter方法对密码进行加密处理，然后从kwargs中移除password键，最后调用父类的构造函数处理其他参数
    # 如果不需要处理不定数量的参数，构造方法可以写成更简单的形式
    # class UserModel:
    #     def __init__(self, username, password):
    #         self.username = username
    #         self.password = password
    #
    # user = UserModel("Alice", "123456")
    def __init__(self, *args, **kwargs):
        if "password" in kwargs:
            self.password = kwargs.get("password")
            kwargs.pop("password")
        super(UserModel, self).__init__(*args, **kwargs)

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, raw_password):
        self._password = generate_password_hash(raw_password)

    def check_password(self, raw_password):
        result = check_password_hash(self.password, raw_password)
        return result

    def has_permission(self, permission):
        return permission in [permission.name for permission in self.role.permissions]
